<?php

class Speedy {

    private $error;
    protected $ePSFacade;
    protected $resultLogin;
    protected $resultClientData;
    protected $registry;

    public function __construct($registry) {
        $this->config = $registry->get('config');
        $this->request = $registry->get('request');
        $this->log = $registry->get('log');
        $this->registry = $registry;

        $this->initConnection();
    }

    protected function initConnection() {
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/util/Util.class.php');
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/EPSFacade.class.php');
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/soap/EPSSOAPInterfaceImpl.class.php');
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/ResultSite.class.php');
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/AddrNomen.class.php');

        try {
            if (!empty($this->request->post['speedy_server_address'])) {
                $server_address = $this->request->post['speedy_server_address'];
            } elseif ($this->config->get('speedy_server_address')) {
                $server_address = $this->config->get('speedy_server_address');
            } else {
                $server_address = 'https://www.speedy.bg/eps/main01.wsdl';
            }

            if (isset($this->request->post['speedy_username'])) {
                $username = $this->request->post['speedy_username'];
            } else {
                $username = $this->config->get('speedy_username');
            }

            if (isset($this->request->post['speedy_password'])) {
                $password = $this->request->post['speedy_password'];
            } else {
                $password = $this->config->get('speedy_password');
            }

            $ePSSOAPInterfaceImpl = new EPSSOAPInterfaceImpl($server_address);
            $this->ePSFacade = new EPSFacade($ePSSOAPInterfaceImpl, $username, $password);
            $this->resultLogin = $this->ePSFacade->login();
            $this->resultClientData = $this->ePSFacade->getClientById($this->resultLogin->getClientId());
        } catch (Exception $e) {
            $this->error = $e->getMessage();
            $this->log->write('Speedy :: initConnection :: ' . $e->getMessage());
        }
    }

    public function getServices() {
        $this->error = '';
        $services = array();
        
        if ($this->resultLogin) {
            try {
                $listServices = $this->ePSFacade->listServices(time());

                if ($listServices) {
                    foreach ($listServices as $service) {
                        if ($service->getTypeId() == 26 || $service->getTypeId() == 36) {
                            continue;
                        }

                        $services[$service->getTypeId()] = $service->getName();
                    }
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getServices :: ' . $e->getMessage());
            }
        }

        return $services;
    }

    public function getOffices($name = null, $city_id = null) {
        $this->error = '';
        $offices = array();

        if (isset($this->resultLogin)) {
            try {
                $listOffices = $this->ePSFacade->listOfficesEx($name, $city_id);
                if ($listOffices) {
                    foreach ($listOffices as $office) {
                        $offices[] = array(
                            'id' => $office->getId(),
                            'label' => $office->getId() . ' ' . $office->getName() . ', ' . $office->getAddress()->getFullAddressString(),
                            'value' => $office->getName()
                        );
                    }
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getOffices :: ' . $e->getMessage());
            }
        }

        return $offices;
    }

    public function getCities($name = null, $postcode = null) {
        $this->error = '';
        $cities = array();

        if (isset($this->resultLogin)) {

            
            try {
                if ($postcode) {
                    require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/ParamFilterSite.class.php');

                    $paramFilterSite = new ParamFilterSite();
                    $paramFilterSite->setPostCode($postcode);

                    $paramFilterSite->setName($name);

                    $listSitesEx = $this->ePSFacade->listSitesEx($paramFilterSite);
                    $listSites = array();

                    foreach ($listSitesEx as $result) {
                        if ($result->isExactMatch()) {
                            $listSites[] = $result->getSite();
                        }
                    }
                } else {
                    $listSites = $this->ePSFacade->listSites(null, $name);
                }

                if ($listSites) {
                    foreach ($listSites as $city) {
                        $cities[] = array(
                            'id' => $city->getId(),
                            'label' => $city->getType() . ' ' . $city->getName() . ' (' . $city->getPostCode() . '), общ. ' . $city->getMunicipality() . ', обл. ' . $city->getRegion(),
                            'value' => $city->getType() . ' ' . $city->getName() . ' (' . $city->getPostCode() . '), общ. ' . $city->getMunicipality() . ', обл. ' . $city->getRegion(),
                            'postcode' => $city->getPostCode(),
                            'nomenclature' => $city->getAddrNomen()->getValue()
                        );
                    }
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getCities :: ' . $e->getMessage());
            }
        }

        return $cities;
    }

    public function getQuarters($name = null, $city_id = null) {
        $this->error = '';
        $quarters = array();

        if (isset($this->resultLogin)) {
            
            try {
                $listQuarters = $this->ePSFacade->listQuarters($name, $city_id);

                if ($listQuarters) {
                    foreach ($listQuarters as $quarter) {
                        $quarters[] = array(
                            'id' => $quarter->getId(),
                            'label' => ($quarter->getType() ? $quarter->getType() . ' ' : '') . $quarter->getName(),
                            'value' => ($quarter->getType() ? $quarter->getType() . ' ' : '') . $quarter->getName()
                        );
                    }
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getQuarters :: ' . $e->getMessage());
            }
        }

        return $quarters;
    }

    public function getStreets($name = null, $city_id = null) {
        $this->error = '';
        $streets = array();

        if (isset($this->resultLogin)) {
           
            try {
                $listStreets = $this->ePSFacade->listStreets($name, $city_id);

                if ($listStreets) {
                    foreach ($listStreets as $street) {
                        $streets[] = array(
                            'id' => $street->getId(),
                            'label' => ($street->getType() ? $street->getType() . ' ' : '') . $street->getName(),
                            'value' => ($street->getType() ? $street->getType() . ' ' : '') . $street->getName()
                        );
                    }
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getStreets :: ' . $e->getMessage());
            }
        }

        return $streets;
    }

    public function getBlocks($name = null, $city_id = null) {
        $this->error = '';
        $blocks = array();

        if (isset($this->resultLogin)) {
           
            try {
                $listBlocks = $this->ePSFacade->listBlocks($name, $city_id);

                if ($listBlocks) {
                    foreach ($listBlocks as $block) {
                        $blocks[] = array(
                            'label' => $block,
                            'value' => $block
                        );
                    }
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getBlocks :: ' . $e->getMessage());
            }
        }

        return $blocks;
    }

    public function calculate($data) {
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/ParamCalculation.class.php');

        $this->error = '';
        $resultCalculation = array();

        if (isset($this->resultLogin)) {
            try {
                $paramCalculation = new ParamCalculation();
                $paramCalculation->setSenderId($this->resultLogin->getClientId());
                $paramCalculation->setBroughtToOffice($this->config->get('speedy_from_office') && $this->config->get('speedy_office_id'));
                $paramCalculation->setToBeCalled($data['to_office'] && $data['office_id']);
                $paramCalculation->setParcelsCount($data['count']);
                $paramCalculation->setWeightDeclared($data['weight']);
                $paramCalculation->setDocuments($this->config->get('speedy_documents'));
                $paramCalculation->setPalletized(false);

                if (!empty($data['fixed_time'])) {
                    $paramCalculation->setFixedTimeDelivery($data['fixed_time']);
                } else {
                    $paramCalculation->setFixedTimeDelivery(null);
                }

                if (isset($data['loading'])) {
                    if ($data['insurance']) {
                        if ($data['fragile']) {
                            $paramCalculation->setFragile(true);
                        } else {
                            $paramCalculation->setFragile(false);
                        }

                        $paramCalculation->setAmountInsuranceBase($data['totalNoShipping']);
                        $paramCalculation->setPayerTypeInsurance(ParamCalculation::PAYER_TYPE_RECEIVER);
                    } else {
                        $paramCalculation->setFragile(false);
                    }
                } elseif ($this->config->get('speedy_insurance')) {
                    if ($this->config->get('speedy_fragile')) {
                        $paramCalculation->setFragile(true);
                    } else {
                        $paramCalculation->setFragile(false);
                    }

                    $paramCalculation->setAmountInsuranceBase($data['totalNoShipping']);
                    $paramCalculation->setPayerTypeInsurance(ParamCalculation::PAYER_TYPE_RECEIVER);
                } else {
                    $paramCalculation->setFragile(false);
                }

                $paramCalculation->setReceiverSiteId($data['city_id']);

                
                    $paramCalculation->setPayerType(ParamCalculation::PAYER_TYPE_RECEIVER);
                

                if ($data['cod']) {
                    $paramCalculation->setAmountCodBase($data['total']);
                } else {
                    $paramCalculation->setAmountCodBase(0);
                }

                $paramCalculation->setTakingDate($data['taking_date']);
                $paramCalculation->setAutoAdjustTakingDate(true);

                $resultCalculation = $this->ePSFacade->calculateMultipleServices($paramCalculation, $this->config->get('speedy_allowed_methods'));

                foreach ($resultCalculation as $key => $service) {
                    if ($service->getErrorDescription()) {
                        unset($resultCalculation[$key]);
                    }
                }

                $resultCalculation = array_values($resultCalculation);
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: calculate :: ' . $e->getMessage());
            }
        }

        return $resultCalculation;
    }

    public function getAllowedDaysForTaking($data) {
        $this->error = '';
        $firstAvailableDate = '';

        if (isset($this->resultLogin)) {
            try {
                if ($this->config->get('speedy_from_office') && $this->config->get('speedy_office_id')) {
                    $senderSiteId = null;
                    $senderOfficeId = $this->config->get('speedy_office_id');
                } else {
                    $senderSiteId = $this->resultClientData->getAddress()->getSiteId();
                    $senderOfficeId = null;
                }

                $takingTime = $this->ePSFacade->getAllowedDaysForTaking($data['shipping_method_id'], $senderSiteId, $senderOfficeId, $data['taking_date']);

                if ($takingTime) {
                    $firstAvailableDate = $takingTime[0];
                }
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: getAllowedDaysForTaking :: ' . $e->getMessage());
            }
        }

        return $firstAvailableDate;
    }

    public function createBillOfLading($data, $order) {
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/ParamCalculation.class.php');

        $this->error = '';
        $bol = array();

        if (isset($this->resultLogin)) {
            try {
                $sender = new ParamClientData();
                $sender->setClientId($this->resultLogin->getClientId());

                if ($this->config->get('speedy_telephone')) {
                    $senderPhone = new ParamPhoneNumber();
                    $senderPhone->setNumber($this->config->get('speedy_telephone'));
                    $sender->setPhones(array(0 => $senderPhone));
                }

                $receiverAddress = new ParamAddress();
                $receiverAddress->setSiteId($data['city_id']);

                if ($data['quarter']) {
                    $receiverAddress->setQuarterName($data['quarter']);
                }

                if ($data['quarter_id']) {
                    $receiverAddress->setQuarterId($data['quarter_id']);
                }

                if ($data['street']) {
                    $receiverAddress->setStreetName($data['street']);
                }

                if ($data['street_id']) {
                    $receiverAddress->setStreetId($data['street_id']);
                }

                if ($data['street_no']) {
                    $receiverAddress->setStreetNo($data['street_no']);
                }

                if ($data['block_no']) {
                    $receiverAddress->setBlockNo($data['block_no']);
                }

                if ($data['entrance_no']) {
                    $receiverAddress->setEntranceNo($data['entrance_no']);
                }

                if ($data['floor_no']) {
                    $receiverAddress->setFloorNo($data['floor_no']);
                }

                if ($data['apartment_no']) {
                    $receiverAddress->setApartmentNo($data['apartment_no']);
                }

                if ($data['note']) {
                    $receiverAddress->setAddressNote($data['note']);
                }

                $receiver = new ParamClientData();
                $receiver->setPartnerName($order['firstname'] . ' ' . $order['lastname']);
                $receiverPhone = new ParamPhoneNumber();
                $receiverPhone->setNumber($order['telephone']);
                $receiver->setPhones(array(0 => $receiverPhone));
                $receiver->setEmail($order['email']);

                $picking = new ParamPicking();
                $picking->setClientSystemId(1310221100); //OpenCart
                $picking->setRef1($order['order_id']);

                if ($data['depth'] || $data['height'] || $data['width']) {
                    $size = new Size();

                    if ($data['depth']) {
                        $size->setDepth($data['depth']);
                    }

                    if ($data['height']) {
                        $size->setHeight($data['height']);
                    }

                    if ($data['width']) {
                        $size->setWidth($data['width']);
                    }

                    $picking->setSize($size);
                }

                if (!empty($data['fixed_time'])) {
                    $picking->setFixedTimeDelivery($data['fixed_time']);
                }

                $picking->setServiceTypeId($data['shipping_method_id']);

                if ($data['to_office'] && $data['office_id']) {
                    $picking->setOfficeToBeCalledId($data['office_id']);
                } else {
                    $receiver->setAddress($receiverAddress);
                    $picking->setOfficeToBeCalledId(null);
                }

                $picking->setBackDocumentsRequest($this->config->get('speedy_back_documents'));
                $picking->setBackReceiptRequest($this->config->get('speedy_back_receipt'));

                if ($this->config->get('speedy_from_office') && $this->config->get('speedy_office_id')) {
                    $picking->setWillBringToOffice(true);
                    $picking->setWillBringToOfficeId($this->config->get('speedy_office_id'));
                } else {
                    $picking->setWillBringToOffice(false);
                }

                $picking->setParcelsCount($data['count']);
                $picking->setWeightDeclared($data['weight']);
                $picking->setContents($data['contents']);
                $picking->setPacking($data['packing']);
                $picking->setPackId(null);
                $picking->setDocuments($this->config->get('speedy_documents'));
                $picking->setPalletized(false);

                $payerType = $this->getPayerType($order['order_id'], $data['shipping_method_cost']);

                if ($data['insurance']) {
                    if ($data['fragile']) {
                        $picking->setFragile(true);
                    } else {
                        $picking->setFragile(false);
                    }

                    $picking->setAmountInsuranceBase($data['totalNoShipping']);
                    /*
                      if ($this->config->get('speedy_pricing') == 'free' || $this->config->get('speedy_pricing') == 'fixed') {
                      $picking->setPayerTypeInsurance($payerType);
                      } else {
                      $picking->setPayerTypeInsurance($payerType);
                      } */
                    $picking->setPayerTypeInsurance($payerType);
                } else {
                    $picking->setFragile(false);
                }

                $picking->setSender($sender);
                $picking->setReceiver($receiver);

                /*
                  if ($this->config->get('speedy_pricing') == 'free' || $this->config->get('speedy_pricing') == 'fixed') {
                  $picking->setPayerType($payerType);
                  } else {
                  $picking->setPayerType($payerType);
                  }

                 */

                $picking->setPayerType($payerType);

                $picking->setTakingDate($data['taking_date']);

                if ($data['deffered_days']) {
                    $picking->setDeferredDeliveryWorkDays($data['deffered_days']);
                }

                if ($data['client_note']) {
                    $picking->setNoteClient($data['client_note']);
                }

                if ($data['cod']) {
                    $picking->setAmountCodBase($data['total']);
                } else {
                    $picking->setAmountCodBase(0);
                }

                $result = $this->ePSFacade->createBillOfLading($picking);
                $parcels = $result->getGeneratedParcels();
                $bol['bol_id'] = $parcels[0]->getParcelId();
                $bol['total'] = $result->getAmounts()->getTotal();
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: createBillOfLading :: ' . $e->getMessage());
            }
        }

        return $bol;
    }

    public function createPDF($bol_id) {
        require_once(DIR_SYSTEM . 'library/speedy-eps-lib/ver01/ParamPDF.class.php');

        $this->error = '';
        $pdf = '';

        if (isset($this->resultLogin)) {
            try {
                $paramPDF = new ParamPDF();

                if ($this->config->get('speedy_label_printer')) {
                    $pickingParcels = $this->ePSFacade->getPickingParcels($bol_id);

                    $ids = array();

                    foreach ($pickingParcels as $parcel) {
                        $ids[] = $parcel->getParcelId();
                    }

                    $paramPDF->setIds($ids);
                    $paramPDF->setType(ParamPDF::PARAM_PDF_TYPE_LBL);
                } else {
                    $paramPDF->setIds($bol_id);
                    $paramPDF->setType(ParamPDF::PARAM_PDF_TYPE_BOL);
                }

                $paramPDF->setIncludeAutoPrintJS(true);

                $pdf = $this->ePSFacade->createPDF($paramPDF);
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: createPDF :: ' . $e->getMessage());
            }
        }

        return $pdf;
    }

    public function requestCourier($bol_ids) {
        $this->error = '';
        $result = array();

        if (isset($this->resultLogin)) {
            try {
                $paramOrder = new ParamOrder();
                $paramOrder->setBillOfLadingsList($bol_ids);
                $paramOrder->setBillOfLadingsToIncludeType(ParamOrder::ORDER_BOL_INCLUDE_TYPE_EXPLICIT);

                if ($this->config->get('speedy_telephone')) {
                    $paramPhoneNumber = new ParamPhoneNumber();
                    $paramPhoneNumber->setNumber($this->config->get('speedy_telephone'));
                    $paramOrder->setPhoneNumber($paramPhoneNumber);
                }

                $paramOrder->setWorkingEndTime($this->config->get('speedy_workingtime_end_hour') . $this->config->get('speedy_workingtime_end_min'));
                $paramOrder->setContactName($this->config->get('speedy_name'));

                $result = $this->ePSFacade->createOrder($paramOrder);
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: requestCourier :: ' . $e->getMessage());
            }
        }

        return $result;
    }

    public function cancelBol($bol_id) {
        $this->error = '';
        $cancelled = false;

        if (isset($this->resultLogin)) {
            try {
                $this->ePSFacade->invalidatePicking($bol_id);
                $cancelled = true;
            } catch (Exception $e) {
                $this->error = $e->getMessage();
                $this->log->write('Speedy :: cancelBol :: ' . $e->getMessage());
            }
        }

        return $cancelled;
    }

    public function getError($type = null) {
        if ($type) {
            if (isset($this->error[$type])) {
                return $this->error[$type];
            } else {
                return false;
            }
        } else {
            return $this->error;
        }
    }
    
    public function setError($error, $type = null){
        if($type){
            $this->error[$type] = $error;
        }else{
            $this->error = $error;
        }
    }

    public function checkCredentials($username, $password) {
        $this->ePSFacade->setUsername($username);
        $this->ePSFacade->setPassword($password);

        try {

            return $this->ePSFacade->login();
        } catch (ClientException $ce) {
            return FALSE;
        } catch (ServerException $se) {
            return FALSE;
        }
    }

    protected function transliteration($value, $language_from = 'en', $language_to = 'bg') {
        $en = array('a', 'b', 'v', 'g', 'd', 'e', 'zh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'tc', 'ch', 'sh', 'sht', 'a', 'y', 'yu', 'ya', 'y', 'e', 'yo', 'A', 'B', 'V', 'G', 'D', 'E', 'Zh', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'Tc', 'Ch', 'Sh', 'Sht', 'A', 'Y', 'Yu', 'Ya', 'Y', 'E', 'Yo', 'q', 'Q');
        $bg = array('а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ь', 'ю', 'я', 'ы', 'э', 'ё', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ь', 'Ю', 'Я', 'Ы', 'Э', 'Ё', 'я', 'Я');

        if ($language_from != $language_to) {
            $value = str_replace(${$language_from}, ${$language_to}, $value);
        }

        return $value;
    }


    private function getPayerType($order_id, $shippingCost) {
        $payerType = null;
        
        
        $db = $this->registry->get('db');
        $session = $this->registry->get('session');
        $query = $db->query("SELECT data FROM " . DB_PREFIX . "speedy_order WHERE order_id = '" . (int) $order_id . "'");

        $data = unserialize($query->row['data']);


        if ($data['price_gen_method'] && !$session->data['is_speedy_bol_recalculated']) {
            if ($data['price_gen_method'] == 'fixed' || $data['price_gen_method'] == 'free') {
                if ($data['price_gen_method'] == 'free') {

                    $delta = 0.0001;

                    if (abs($data['shipping_method_cost'] - 0.0000) < $delta) {
                        $payerType = ParamCalculation::PAYER_TYPE_SENDER;
                    } else {
                        $payerType = ParamCalculation::PAYER_TYPE_RECEIVER;
                    }
                } else {
                    $payerType = ParamCalculation::PAYER_TYPE_SENDER;
                }
            } else {
                $payerType = ParamCalculation::PAYER_TYPE_RECEIVER;
            }
        } elseif ($data['price_gen_method'] && $session->data['is_speedy_bol_recalculated']) {
            if ($this->config->get('speedy_pricing') == 'free' || $this->config->get('speedy_pricing') == 'fixed') {
                if ($this->config->get('speedy_pricing') == 'free') {

                    $delta = 0.0001;
 

                    if (($shippingCost - 0.0000) < $delta) {
                        $payerType = ParamCalculation::PAYER_TYPE_SENDER;
                    } else {
                        $payerType = ParamCalculation::PAYER_TYPE_RECEIVER;
                    }
                }else{
                    $payerType = ParamCalculation::PAYER_TYPE_SENDER;
                }


               
            }else{
                $payerType = ParamCalculation::PAYER_TYPE_RECEIVER;
            }
        } elseif (!$data['price_gen_method']) {
            if ($this->config->get('speedy_pricing') == 'free' || $this->config->get('speedy_pricing') == 'fixed') {
                $payerType = ParamCalculation::PAYER_TYPE_SENDER;
            } else {
                $payerType = ParamCalculation::PAYER_TYPE_RECEIVER;
            }
        }


        return $payerType;
    }

}

?>